
#include <BLabel>
#include <BHBoxLayout>
#include <BVBoxLayout>
#include <BGridLayout>
#include <BPainter>
#include <BMouseEvent>
#include <BCursor>

#include "CutoffImageDialog.h"

CutoffImageDialog::CutoffImageDialog(BWidget* parent) : BDialog(parent)
{
	this->setTitle("Cutoff");

	_imageSpacer = new BSpacer();

	BGridLayout* gridLayout = new BGridLayout();
	{
		_widthSpinBox = new BSpinBox(0, 999999);
		_resetWidthButton = new BButton("reset");
		_heightSpinBox = new BSpinBox(0, 999999);
		_resetHeightButton = new BButton("reset");
		gridLayout->addWidget(0, 0, new BLabel("width"));
		gridLayout->addWidget(0, 1, _widthSpinBox);
		gridLayout->addWidget(0, 2, _resetWidthButton);
		gridLayout->addWidget(1, 0, new BLabel("height"));
		gridLayout->addWidget(1, 1, _heightSpinBox);
		gridLayout->addWidget(1, 2, _resetHeightButton);
	}

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addSpacer(_imageSpacer);
	vlayout->addLayout(gridLayout, 0);

	BHBoxLayout* bottomLayout = new BHBoxLayout(this, Part_Bottom);
	{
		_confirmButton = new BButton("confirm");
		_cancelButton = new BButton("cancel");
		bottomLayout->addSpring();
		bottomLayout->addWidget(_confirmButton);
		bottomLayout->addSpacer(10);
		bottomLayout->addWidget(_cancelButton);
	}

	connect(_confirmButton, Signal_Clicked, &CutoffImageDialog::slotConfirmButtonClicked);
	connect(_cancelButton, Signal_Clicked, &CutoffImageDialog::slotCancelButtonClicked);

}
CutoffImageDialog::~CutoffImageDialog()
{

}

void CutoffImageDialog::setImage(BImage* image)
{
	_image = image;
	if (_image)
	{
		BString widthSuffix;
		widthSuffix << '/' << _image->width();
		_widthSpinBox->setValue(_image->width());
		_widthSpinBox->setSuffix(widthSuffix);
		_widthSpinBox->setSuffixAlign(Align_RightCenter);

		BString heightSuffix;
		heightSuffix << '/' << _image->height();
		_heightSpinBox->setValue(_image->height());
		_heightSpinBox->setSuffix(heightSuffix);
		_heightSpinBox->setSuffixAlign(Align_RightCenter);

	}
	this->fresh();
}
BImage* CutoffImageDialog::image()
{
	return _image;
}

void CutoffImageDialog::slotConfirmButtonClicked()
{
	BRect rect = _cutRect - _imageRect.pos();
	BImage* image = new BImage();
	_image->clone(rect, image);
	_image = image;
	this->close(true);
}
void CutoffImageDialog::slotCancelButtonClicked()
{
	this->close();
}

void CutoffImageDialog::adjustEvent(const BEvent& event)
{
	BDialog::adjustEvent(event);
	BSize imageSize = _imageSpacer->rect().wrap(_image->size());
	_imageRect = _imageSpacer->rect().align(Align_Center, imageSize);
	if (_cutRect.width() < 1)
		_cutRect.setWidth(imageSize.width());
	if (_cutRect.height() < 1)
		_cutRect.setHeight(imageSize.height());
	_cutRect = _imageRect.wrap(_cutRect);
}

void CutoffImageDialog::styleEvent(const BEvent& event)
{
	BDialog::styleEvent(event);
}
void CutoffImageDialog::freshEvent(const BEvent& event)
{
	BDialog::freshEvent(event);
}
void CutoffImageDialog::paintEvent(const BEvent& event)
{
	BDialog::paintEvent(event);
	BPainter painter(this);
	painter.setColor(200, 0, 0);
	painter.drawRect(_imageSpacer->rect());
	if (_image)
	{
		painter.drawImage(_imageRect, _image);
		painter.setLineStipple(0xFF00);
		painter.setColor(0, 100, 100);
		painter.drawRect(_cutRect);
		painter.setLineStipple(0);
	}
}

void CutoffImageDialog::mousePressEvent(const BMouseEvent& mouseEvent)
{
	if (mouseEvent.button() == Button_Left)
	{
		_pressed = true;
		_pressedPoint = mouseEvent.pos();
		_pressedRect = _cutRect;
		this->fresh();
	}
	BDialog::mousePressEvent(mouseEvent);
}
void CutoffImageDialog::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{
	if (mouseEvent.button() == Button_Left)
	{
		const BPoint& pos = mouseEvent.pos();
		_pressed = false;
		_pressedRect.reset();
		this->fresh();
	}
	BDialog::mouseReleaseEvent(mouseEvent);
}
void CutoffImageDialog::mouseMoveEvent(const BMouseEvent& mouseEvent)
{
	const BPoint& pos = mouseEvent.pos();
	if (_pressed)
	{
		if (_resizePart)
		{
			BPoint offset = pos - _pressedPoint;
			BRect rect = _pressedRect;
			if (_resizePart & Part_Left)
				rect.left() = rect.left() + offset.x();
			if (_resizePart & Part_Top)
				rect.top() = rect.top() + offset.y();
			if (_resizePart & Part_Right)
				rect.right() = rect.right() + offset.x();
			if (_resizePart & Part_Bottom)
				rect.bottom() = rect.bottom() + offset.y();
			if (rect.left() < _imageRect.left())
				rect.left() = _imageRect.left();
			if (rect.right() > _imageRect.right())
				rect.right() = _imageRect.right();
			if (rect.top() < _imageRect.top())
				rect.top() = _imageRect.top();
			if (rect.bottom() > _imageRect.bottom())
				rect.bottom() = _imageRect.bottom();
			_cutRect = rect;
			_widthSpinBox->setValue(_cutRect.width());
			_heightSpinBox->setValue(_cutRect.height());
			this->fresh();
			return;
		}
	}
	else
	{
		CursorType type = Cursor_None;
		_resizePart = Part_None;
		_borderLeft.set(_cutRect.left() - 5, _cutRect.top(), 5, _cutRect.height());
		_borderTop.set(_cutRect.left(), _cutRect.top() - 5, _cutRect.width(), 5);
		_borderRight.set(_cutRect.right(), _cutRect.top(), 5, _cutRect.height());
		_borderBottom.set(_cutRect.left(), _cutRect.bottom(), _cutRect.width(), 5);
		_borderLeftTop.set(_cutRect.left() - 5, _cutRect.top() - 5, 5, 5);
		_borderLeftBottom.set(_cutRect.left() - 5, _cutRect.bottom(), 5, 5);
		_borderRightTop.set(_cutRect.right(), _cutRect.top() - 5, 5, 5);
		_borderRightBottom.set(_cutRect.right(), _cutRect.bottom(), 5, 5);

		if (_borderLeftTop.contain(pos))
		{
			_resizePart = Part_LeftTop;
			type = Cursor_SizeLeftTop;
		}
		else if (_borderLeftBottom.contain(pos))
		{
			_resizePart = Part_LeftBottom;
			type = Cursor_SizeLeftBottom;
		}
		else if (_borderRightTop.contain(pos))
		{
			_resizePart = Part_RightTop;
			type = Cursor_SizeRightTop;
		}
		else if (_borderRightBottom.contain(pos))
		{
			_resizePart = Part_RightBottom;
			type = Cursor_SizeRightBottom;
		}
		else if (_borderLeft.contain(pos))
		{
			_resizePart = Part_Left;
			type = Cursor_SizeHor;
		}
		else if (_borderRight.contain(pos))
		{
			_resizePart = Part_Right;
			type = Cursor_SizeHor;
		}
		else if (_borderTop.contain(pos))
		{
			_resizePart = Part_Top;
			type = Cursor_SizeVer;
		}
		else if (_borderBottom.contain(pos))
		{
			_resizePart = Part_Bottom;
			type = Cursor_SizeVer;
		}
		if (!this->cursor() || this->cursor()->type() != type)
		{
			this->setCursor(type);
		}
	}
	if (!_resizePart)
		BDialog::mouseMoveEvent(mouseEvent);
}
